home *** CD-ROM | disk | FTP | other *** search
/ CD Actual Thematic 7: Programming / CDAT7.iso / Share / Codigo / hh / rsource.exe / Heretic Source / P_PSPR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-13  |  43.7 KB  |  1,870 lines

  1.  
  2. // P_pspr.c
  3.  
  4. #include "DoomDef.h"
  5. #include "P_local.h"
  6. #include "soundst.h"
  7.  
  8. // Macros
  9.  
  10. #define LOWERSPEED FRACUNIT*6
  11. #define RAISESPEED FRACUNIT*6
  12. #define WEAPONBOTTOM 128*FRACUNIT
  13. #define WEAPONTOP 32*FRACUNIT
  14. #define FLAME_THROWER_TICS 10*35
  15. #define MAGIC_JUNK 1234
  16. #define MAX_MACE_SPOTS 8
  17.  
  18. static int MaceSpotCount;
  19. static struct
  20. {
  21.     fixed_t x;
  22.     fixed_t y;
  23. } MaceSpots[MAX_MACE_SPOTS];
  24.  
  25. fixed_t bulletslope;
  26.  
  27. static int WeaponAmmoUsePL1[NUMWEAPONS] = {
  28.     0,                    // staff
  29.     USE_GWND_AMMO_1,    // gold wand
  30.     USE_CBOW_AMMO_1,    // crossbow
  31.     USE_BLSR_AMMO_1,    // blaster
  32.     USE_SKRD_AMMO_1,    // skull rod
  33.     USE_PHRD_AMMO_1,    // phoenix rod
  34.     USE_MACE_AMMO_1,    // mace
  35.     0,                    // gauntlets
  36.     0                    // beak
  37. };
  38.  
  39. static int WeaponAmmoUsePL2[NUMWEAPONS] = {
  40.     0,                    // staff
  41.     USE_GWND_AMMO_2,    // gold wand
  42.     USE_CBOW_AMMO_2,    // crossbow
  43.     USE_BLSR_AMMO_2,    // blaster
  44.     USE_SKRD_AMMO_2,    // skull rod
  45.     USE_PHRD_AMMO_2,    // phoenix rod
  46.     USE_MACE_AMMO_2,    // mace
  47.     0,                    // gauntlets
  48.     0                    // beak
  49. };
  50.  
  51. weaponinfo_t wpnlev1info[NUMWEAPONS] =
  52. {
  53.     { // Staff
  54.         am_noammo,            // ammo
  55.         S_STAFFUP,            // upstate
  56.         S_STAFFDOWN,        // downstate
  57.         S_STAFFREADY,        // readystate
  58.         S_STAFFATK1_1,        // atkstate
  59.         S_STAFFATK1_1,        // holdatkstate
  60.         S_NULL                // flashstate
  61.     },
  62.     { // Gold wand
  63.         am_goldwand,        // ammo
  64.         S_GOLDWANDUP,        // upstate
  65.         S_GOLDWANDDOWN,        // downstate
  66.         S_GOLDWANDREADY,    // readystate
  67.         S_GOLDWANDATK1_1,    // atkstate
  68.         S_GOLDWANDATK1_1,    // holdatkstate
  69.         S_NULL                // flashstate
  70.     },
  71.     { // Crossbow
  72.         am_crossbow,        // ammo
  73.         S_CRBOWUP,            // upstate
  74.         S_CRBOWDOWN,        // downstate
  75.         S_CRBOW1,            // readystate
  76.         S_CRBOWATK1_1,        // atkstate
  77.         S_CRBOWATK1_1,        // holdatkstate
  78.         S_NULL                // flashstate
  79.     },
  80.     { // Blaster
  81.         am_blaster,            // ammo
  82.         S_BLASTERUP,        // upstate
  83.         S_BLASTERDOWN,        // downstate
  84.         S_BLASTERREADY,        // readystate
  85.         S_BLASTERATK1_1,    // atkstate
  86.         S_BLASTERATK1_3,    // holdatkstate
  87.         S_NULL                // flashstate
  88.     },
  89.     { // Skull rod
  90.         am_skullrod,        // ammo
  91.         S_HORNRODUP,        // upstate
  92.         S_HORNRODDOWN,        // downstate
  93.         S_HORNRODREADY,        // readystae
  94.         S_HORNRODATK1_1,    // atkstate
  95.         S_HORNRODATK1_1,    // holdatkstate
  96.         S_NULL                // flashstate
  97.     },
  98.     { // Phoenix rod
  99.         am_phoenixrod,        // ammo
  100.         S_PHOENIXUP,        // upstate
  101.         S_PHOENIXDOWN,        // downstate
  102.         S_PHOENIXREADY,        // readystate
  103.         S_PHOENIXATK1_1,    // atkstate
  104.         S_PHOENIXATK1_1,    // holdatkstate
  105.         S_NULL                // flashstate
  106.     },
  107.     { // Mace
  108.         am_mace,            // ammo
  109.         S_MACEUP,            // upstate
  110.         S_MACEDOWN,            // downstate
  111.         S_MACEREADY,        // readystate
  112.         S_MACEATK1_1,        // atkstate
  113.         S_MACEATK1_2,        // holdatkstate
  114.         S_NULL                // flashstate
  115.     },
  116.     { // Gauntlets
  117.         am_noammo,            // ammo
  118.         S_GAUNTLETUP,        // upstate
  119.         S_GAUNTLETDOWN,        // downstate
  120.         S_GAUNTLETREADY,    // readystate
  121.         S_GAUNTLETATK1_1,    // atkstate
  122.         S_GAUNTLETATK1_3,    // holdatkstate
  123.         S_NULL                // flashstate
  124.     },
  125.     { // Beak
  126.         am_noammo,            // ammo
  127.         S_BEAKUP,            // upstate
  128.         S_BEAKDOWN,            // downstate
  129.         S_BEAKREADY,        // readystate
  130.         S_BEAKATK1_1,        // atkstate
  131.         S_BEAKATK1_1,        // holdatkstate
  132.         S_NULL                // flashstate
  133.     }
  134. };
  135.  
  136. weaponinfo_t wpnlev2info[NUMWEAPONS] =
  137. {
  138.     { // Staff
  139.         am_noammo,            // ammo
  140.         S_STAFFUP2,            // upstate
  141.         S_STAFFDOWN2,        // downstate
  142.         S_STAFFREADY2_1,    // readystate
  143.         S_STAFFATK2_1,        // atkstate
  144.         S_STAFFATK2_1,        // holdatkstate
  145.         S_NULL                // flashstate
  146.     },
  147.     { // Gold wand
  148.         am_goldwand,        // ammo
  149.         S_GOLDWANDUP,        // upstate
  150.         S_GOLDWANDDOWN,        // downstate
  151.         S_GOLDWANDREADY,    // readystate
  152.         S_GOLDWANDATK2_1,    // atkstate
  153.         S_GOLDWANDATK2_1,    // holdatkstate
  154.         S_NULL                // flashstate
  155.     },
  156.     { // Crossbow
  157.         am_crossbow,        // ammo
  158.         S_CRBOWUP,            // upstate
  159.         S_CRBOWDOWN,        // downstate
  160.         S_CRBOW1,            // readystate
  161.         S_CRBOWATK2_1,        // atkstate
  162.         S_CRBOWATK2_1,        // holdatkstate
  163.         S_NULL                // flashstate
  164.     },
  165.     { // Blaster
  166.         am_blaster,            // ammo
  167.         S_BLASTERUP,        // upstate
  168.         S_BLASTERDOWN,        // downstate
  169.         S_BLASTERREADY,        // readystate
  170.         S_BLASTERATK2_1,    // atkstate
  171.         S_BLASTERATK2_3,    // holdatkstate
  172.         S_NULL                // flashstate
  173.     },
  174.     { // Skull rod
  175.         am_skullrod,        // ammo
  176.         S_HORNRODUP,        // upstate
  177.         S_HORNRODDOWN,        // downstate
  178.         S_HORNRODREADY,        // readystae
  179.         S_HORNRODATK2_1,    // atkstate
  180.         S_HORNRODATK2_1,    // holdatkstate
  181.         S_NULL                // flashstate
  182.     },
  183.     { // Phoenix rod
  184.         am_phoenixrod,        // ammo
  185.         S_PHOENIXUP,        // upstate
  186.         S_PHOENIXDOWN,        // downstate
  187.         S_PHOENIXREADY,        // readystate
  188.         S_PHOENIXATK2_1,    // atkstate
  189.         S_PHOENIXATK2_2,    // holdatkstate
  190.         S_NULL                // flashstate
  191.     },
  192.     { // Mace
  193.         am_mace,            // ammo
  194.         S_MACEUP,            // upstate
  195.         S_MACEDOWN,            // downstate
  196.         S_MACEREADY,        // readystate
  197.         S_MACEATK2_1,        // atkstate
  198.         S_MACEATK2_1,        // holdatkstate
  199.         S_NULL                // flashstate
  200.     },
  201.     { // Gauntlets
  202.         am_noammo,            // ammo
  203.         S_GAUNTLETUP2,        // upstate
  204.         S_GAUNTLETDOWN2,    // downstate
  205.         S_GAUNTLETREADY2_1,    // readystate
  206.         S_GAUNTLETATK2_1,    // atkstate
  207.         S_GAUNTLETATK2_3,    // holdatkstate
  208.         S_NULL                // flashstate
  209.     },
  210.     { // Beak
  211.         am_noammo,            // ammo
  212.         S_BEAKUP,            // upstate
  213.         S_BEAKDOWN,            // downstate
  214.         S_BEAKREADY,        // readystate
  215.         S_BEAKATK2_1,        // atkstate
  216.         S_BEAKATK2_1,        // holdatkstate
  217.         S_NULL                // flashstate
  218.     }
  219. };
  220.  
  221. //---------------------------------------------------------------------------
  222. //
  223. // PROC P_OpenWeapons
  224. //
  225. // Called at level load before things are loaded.
  226. //
  227. //---------------------------------------------------------------------------
  228.  
  229. void P_OpenWeapons(void)
  230. {
  231.     MaceSpotCount = 0;
  232. }
  233.  
  234. //---------------------------------------------------------------------------
  235. //
  236. // PROC P_AddMaceSpot
  237. //
  238. //---------------------------------------------------------------------------
  239.  
  240. void P_AddMaceSpot(mapthing_t *mthing)
  241. {
  242.     if(MaceSpotCount == MAX_MACE_SPOTS)
  243.     {
  244.         I_Error("Too many mace spots.");
  245.     }
  246.     MaceSpots[MaceSpotCount].x = mthing->x<<FRACBITS;
  247.     MaceSpots[MaceSpotCount].y = mthing->y<<FRACBITS;
  248.     MaceSpotCount++;
  249. }
  250.  
  251. //---------------------------------------------------------------------------
  252. //
  253. // PROC P_RepositionMace
  254. //
  255. // Chooses the next spot to place the mace.
  256. //
  257. //---------------------------------------------------------------------------
  258.  
  259. void P_RepositionMace(mobj_t *mo)
  260. {
  261.     int spot;
  262.     subsector_t *ss;
  263.  
  264.     P_UnsetThingPosition(mo);
  265.     spot = P_Random()%MaceSpotCount;
  266.     mo->x = MaceSpots[spot].x;
  267.     mo->y = MaceSpots[spot].y;
  268.     ss = R_PointInSubsector(mo->x, mo->y);
  269.     mo->z = mo->floorz = ss->sector->floorheight;
  270.     mo->ceilingz = ss->sector->ceilingheight;
  271.     P_SetThingPosition(mo);
  272. }
  273.  
  274. //---------------------------------------------------------------------------
  275. //
  276. // PROC P_CloseWeapons
  277. //
  278. // Called at level load after things are loaded.
  279. //
  280. //---------------------------------------------------------------------------
  281.  
  282. void P_CloseWeapons(void)
  283. {
  284.     int spot;
  285.  
  286.     if(!MaceSpotCount)
  287.     { // No maces placed
  288.         return;
  289.     }
  290.     if(!deathmatch && P_Random() < 64)
  291.     { // Sometimes doesn't show up if not in deathmatch
  292.         return;
  293.     }
  294.     spot = P_Random()%MaceSpotCount;
  295.     P_SpawnMobj(MaceSpots[spot].x, MaceSpots[spot].y, ONFLOORZ, MT_WMACE);
  296. }
  297.  
  298. //---------------------------------------------------------------------------
  299. //
  300. // PROC P_SetPsprite
  301. //
  302. //---------------------------------------------------------------------------
  303.  
  304. void P_SetPsprite(player_t *player, int position, statenum_t stnum)
  305. {
  306.     pspdef_t *psp;
  307.     state_t *state;
  308.  
  309.     psp = &player->psprites[position];
  310.     do
  311.     {
  312.         if(!stnum)
  313.         { // Object removed itself.
  314.             psp->state = NULL;
  315.             break;
  316.         }
  317.         state = &states[stnum];
  318.         psp->state = state;
  319.         psp->tics = state->tics; // could be 0
  320.         if(state->misc1)
  321.         { // Set coordinates.
  322.             psp->sx = state->misc1<<FRACBITS;
  323.             psp->sy = state->misc2<<FRACBITS;
  324.         }
  325.         if(state->action)
  326.         { // Call action routine.
  327.             state->action(player, psp);
  328.             if(!psp->state)
  329.             {
  330.                 break;
  331.             }
  332.         }
  333.         stnum = psp->state->nextstate;
  334.     } while(!psp->tics); // An initial state of 0 could cycle through.
  335. }
  336.  
  337. /*
  338. =================
  339. =
  340. = P_CalcSwing
  341. =
  342. =================
  343. */
  344.  
  345. /*
  346. fixed_t    swingx, swingy;
  347. void P_CalcSwing (player_t *player)
  348. {
  349.     fixed_t    swing;
  350.     int        angle;
  351.  
  352. // OPTIMIZE: tablify this
  353.  
  354.     swing = player->bob;
  355.  
  356.     angle = (FINEANGLES/70*leveltime)&FINEMASK;
  357.     swingx = FixedMul ( swing, finesine[angle]);
  358.  
  359.     angle = (FINEANGLES/70*leveltime+FINEANGLES/2)&FINEMASK;
  360.     swingy = -FixedMul ( swingx, finesine[angle]);
  361. }
  362. */
  363.  
  364. //---------------------------------------------------------------------------
  365. //
  366. // PROC P_ActivateBeak
  367. //
  368. //---------------------------------------------------------------------------
  369.  
  370. void P_ActivateBeak(player_t *player)
  371. {
  372.     player->pendingweapon = wp_nochange;
  373.     player->readyweapon = wp_beak;
  374.     player->psprites[ps_weapon].sy = WEAPONTOP;
  375.     P_SetPsprite(player, ps_weapon, S_BEAKREADY);
  376. }
  377.  
  378. //---------------------------------------------------------------------------
  379. //
  380. // PROC P_PostChickenWeapon
  381. //
  382. //---------------------------------------------------------------------------
  383.  
  384. void P_PostChickenWeapon(player_t *player, weapontype_t weapon)
  385. {
  386.     if(weapon == wp_beak)
  387.     { // Should never happen
  388.         weapon = wp_staff;
  389.     }
  390.     player->pendingweapon = wp_nochange;
  391.     player->readyweapon = weapon;
  392.     player->psprites[ps_weapon].sy = WEAPONBOTTOM;
  393.     P_SetPsprite(player, ps_weapon, wpnlev1info[weapon].upstate);
  394. }
  395.  
  396. //---------------------------------------------------------------------------
  397. //
  398. // PROC P_BringUpWeapon
  399. //
  400. // Starts bringing the pending weapon up from the bottom of the screen.
  401. //
  402. //---------------------------------------------------------------------------
  403.  
  404. void P_BringUpWeapon(player_t *player)
  405. {
  406.     statenum_t new;
  407.  
  408.     if(player->pendingweapon == wp_nochange)
  409.     {
  410.         player->pendingweapon = player->readyweapon;
  411.     }
  412.     if(player->pendingweapon == wp_gauntlets)
  413.     {
  414.         S_StartSound(player->mo, sfx_gntact);
  415.     }
  416.     if(player->powers[pw_weaponlevel2])
  417.     {
  418.         new = wpnlev2info[player->pendingweapon].upstate;
  419.     }
  420.     else
  421.     {
  422.         new = wpnlev1info[player->pendingweapon].upstate;
  423.     }
  424.     player->pendingweapon = wp_nochange;
  425.     player->psprites[ps_weapon].sy = WEAPONBOTTOM;
  426.     P_SetPsprite(player, ps_weapon, new);
  427. }
  428.  
  429. //---------------------------------------------------------------------------
  430. //
  431. // FUNC P_CheckAmmo
  432. //
  433. // Returns true if there is enough ammo to shoot.  If not, selects the
  434. // next weapon to use.
  435. //
  436. //---------------------------------------------------------------------------
  437.  
  438. boolean P_CheckAmmo(player_t *player)
  439. {
  440.     ammotype_t ammo;
  441.     int *ammoUse;
  442.     int count;
  443.  
  444.     ammo = wpnlev1info[player->readyweapon].ammo;
  445.     if(player->powers[pw_weaponlevel2] && !deathmatch)
  446.     {
  447.         ammoUse = WeaponAmmoUsePL2;
  448.     }
  449.     else
  450.     {
  451.         ammoUse = WeaponAmmoUsePL1;
  452.     }
  453.     count = ammoUse[player->readyweapon];
  454.     if(ammo == am_noammo || player->ammo[ammo] >= count)
  455.     {
  456.         return(true);
  457.     }
  458.     // out of ammo, pick a weapon to change to
  459.     do
  460.     {
  461.         if(player->weaponowned[wp_skullrod]
  462.             && player->ammo[am_skullrod] > ammoUse[wp_skullrod])
  463.         {
  464.             player->pendingweapon = wp_skullrod;
  465.         }
  466.         else if(player->weaponowned[wp_blaster]
  467.             && player->ammo[am_blaster] > ammoUse[wp_blaster])
  468.         {
  469.             player->pendingweapon = wp_blaster;
  470.         }
  471.         else if(player->weaponowned[wp_crossbow]
  472.             && player->ammo[am_crossbow] > ammoUse[wp_crossbow])
  473.         {
  474.             player->pendingweapon = wp_crossbow;
  475.         }
  476.         else if(player->weaponowned[wp_mace]
  477.             && player->ammo[am_mace] > ammoUse[wp_mace])
  478.         {
  479.             player->pendingweapon = wp_mace;
  480.         }
  481.         else if(player->ammo[am_goldwand] > ammoUse[wp_goldwand])
  482.         {
  483.             player->pendingweapon = wp_goldwand;
  484.         }
  485.         else if(player->weaponowned[wp_gauntlets])
  486.         {
  487.             player->pendingweapon = wp_gauntlets;
  488.         }
  489.         else if(player->weaponowned[wp_phoenixrod]
  490.             && player->ammo[am_phoenixrod] > ammoUse[wp_phoenixrod])
  491.         {
  492.             player->pendingweapon = wp_phoenixrod;
  493.         }
  494.         else
  495.         {
  496.             player->pendingweapon = wp_staff;
  497.         }
  498.     } while(player->pendingweapon == wp_nochange);
  499.     if(player->powers[pw_weaponlevel2])
  500.     {
  501.         P_SetPsprite(player, ps_weapon,
  502.             wpnlev2info[player->readyweapon].downstate);
  503.     }
  504.     else
  505.     {
  506.         P_SetPsprite(player, ps_weapon,
  507.             wpnlev1info[player->readyweapon].downstate);
  508.     }
  509.     return(false);
  510. }
  511.  
  512. //---------------------------------------------------------------------------
  513. //
  514. // PROC P_FireWeapon
  515. //
  516. //---------------------------------------------------------------------------
  517.  
  518. void P_FireWeapon(player_t *player)
  519. {
  520.     weaponinfo_t *wpinfo;
  521.     statenum_t attackState;
  522.  
  523.     if(!P_CheckAmmo(player))
  524.     {
  525.         return;
  526.     }
  527.     P_SetMobjState(player->mo, S_PLAY_ATK2);
  528.     wpinfo = player->powers[pw_weaponlevel2] ? &wpnlev2info[0]
  529.         : &wpnlev1info[0];
  530.     attackState = player->refire ? wpinfo[player->readyweapon].holdatkstate
  531.         : wpinfo[player->readyweapon].atkstate;
  532.     P_SetPsprite(player, ps_weapon, attackState);
  533.     P_NoiseAlert(player->mo, player->mo);
  534.     if(player->readyweapon == wp_gauntlets && !player->refire)
  535.     { // Play the sound for the initial gauntlet attack
  536.         S_StartSound(player->mo, sfx_gntuse);
  537.     }
  538. }
  539.  
  540. //---------------------------------------------------------------------------
  541. //
  542. // PROC P_DropWeapon
  543. //
  544. // The player died, so put the weapon away.
  545. //
  546. //---------------------------------------------------------------------------
  547.  
  548. void P_DropWeapon(player_t *player)
  549. {
  550.     if(player->powers[pw_weaponlevel2])
  551.     {
  552.         P_SetPsprite(player, ps_weapon,
  553.             wpnlev2info[player->readyweapon].downstate);
  554.     }
  555.     else
  556.     {
  557.         P_SetPsprite(player, ps_weapon,
  558.             wpnlev1info[player->readyweapon].downstate);
  559.     }
  560. }
  561.  
  562. //---------------------------------------------------------------------------
  563. //
  564. // PROC A_WeaponReady
  565. //
  566. // The player can fire the weapon or change to another weapon at this time.
  567. //
  568. //---------------------------------------------------------------------------
  569.  
  570. void A_WeaponReady(player_t *player, pspdef_t *psp)
  571. {
  572.     int angle;
  573.  
  574.     if(player->chickenTics)
  575.     { // Change to the chicken beak
  576.         P_ActivateBeak(player);
  577.         return;
  578.     }
  579.     // Change player from attack state
  580.     if(player->mo->state == &states[S_PLAY_ATK1]
  581.         || player->mo->state == &states[S_PLAY_ATK2])
  582.     {
  583.         P_SetMobjState(player->mo, S_PLAY);
  584.     }
  585.     // Check for staff PL2 active sound
  586.     if((player->readyweapon == wp_staff)
  587.         && (psp->state == &states[S_STAFFREADY2_1])
  588.         && P_Random() < 128)
  589.     {
  590.         S_StartSound(player->mo, sfx_stfcrk);
  591.     }
  592.     // Put the weapon away if the player has a pending weapon or has
  593.     // died.
  594.     if(player->pendingweapon != wp_nochange || !player->health)
  595.     {
  596.         if(player->powers[pw_weaponlevel2])
  597.         {
  598.             P_SetPsprite(player, ps_weapon,
  599.                 wpnlev2info[player->readyweapon].downstate);
  600.         }
  601.         else
  602.         {
  603.             P_SetPsprite(player, ps_weapon,
  604.                 wpnlev1info[player->readyweapon].downstate);
  605.         }
  606.         return;
  607.     }
  608.  
  609.     // Check for fire.  The phoenix rod does not auto fire.
  610.     if(player->cmd.buttons&BT_ATTACK)
  611.     {
  612.         if(!player->attackdown || (player->readyweapon != wp_phoenixrod))
  613.         {
  614.             player->attackdown = true;
  615.             P_FireWeapon(player);
  616.             return;
  617.         }
  618.     }
  619.     else
  620.     {
  621.         player->attackdown = false;
  622.     }
  623.  
  624.     // Bob the weapon based on movement speed.
  625.     angle = (128*leveltime)&FINEMASK;
  626.     psp->sx = FRACUNIT+FixedMul(player->bob, finecosine[angle]);
  627.     angle &= FINEANGLES/2-1;
  628.     psp->sy = WEAPONTOP+FixedMul(player->bob, finesine[angle]);
  629. }
  630.  
  631. //---------------------------------------------------------------------------
  632. //
  633. // PROC P_UpdateBeak
  634. //
  635. //---------------------------------------------------------------------------
  636.  
  637. void P_UpdateBeak(player_t *player, pspdef_t *psp)
  638. {
  639.     psp->sy = WEAPONTOP+(player->chickenPeck<<(FRACBITS-1));
  640. }
  641.  
  642. //---------------------------------------------------------------------------
  643. //
  644. // PROC A_BeakReady
  645. //
  646. //---------------------------------------------------------------------------
  647.  
  648. void A_BeakReady(player_t *player, pspdef_t *psp)
  649. {
  650.     if(player->cmd.buttons&BT_ATTACK)
  651.     { // Chicken beak attack
  652.         player->attackdown = true;
  653.         P_SetMobjState(player->mo, S_CHICPLAY_ATK1);
  654.         if(player->powers[pw_weaponlevel2])
  655.         {
  656.             P_SetPsprite(player, ps_weapon, S_BEAKATK2_1);
  657.         }
  658.         else
  659.         {
  660.             P_SetPsprite(player, ps_weapon, S_BEAKATK1_1);
  661.         }
  662.         P_NoiseAlert(player->mo, player->mo);
  663.     }
  664.     else
  665.     {
  666.         if(player->mo->state == &states[S_CHICPLAY_ATK1])
  667.         { // Take out of attack state
  668.             P_SetMobjState(player->mo, S_CHICPLAY);
  669.         }
  670.         player->attackdown = false;
  671.     }
  672. }
  673.  
  674. //---------------------------------------------------------------------------
  675. //
  676. // PROC A_ReFire
  677. //
  678. // The player can re fire the weapon without lowering it entirely.
  679. //
  680. //---------------------------------------------------------------------------
  681.  
  682. void A_ReFire(player_t *player, pspdef_t *psp)
  683. {
  684.     if((player->cmd.buttons&BT_ATTACK)
  685.         && player->pendingweapon == wp_nochange && player->health)
  686.     {
  687.         player->refire++;
  688.         P_FireWeapon(player);
  689.     }
  690.     else
  691.     {
  692.         player->refire = 0;
  693.         P_CheckAmmo(player);
  694.     }
  695. }
  696.  
  697. //---------------------------------------------------------------------------
  698. //
  699. // PROC A_Lower
  700. //
  701. //---------------------------------------------------------------------------
  702.  
  703. void A_Lower(player_t *player, pspdef_t *psp)
  704. {
  705.     if(player->chickenTics)
  706.     {
  707.         psp->sy = WEAPONBOTTOM;
  708.     }
  709.     else
  710.     {
  711.         psp->sy += LOWERSPEED;
  712.     }
  713.     if(psp->sy < WEAPONBOTTOM)
  714.     { // Not lowered all the way yet
  715.         return;
  716.     }
  717.     if(player->playerstate == PST_DEAD)
  718.     { // Player is dead, so don't bring up a pending weapon
  719.         psp->sy = WEAPONBOTTOM;
  720.         return;
  721.     }
  722.     if(!player->health)
  723.     { // Player is dead, so keep the weapon off screen
  724.         P_SetPsprite(player,  ps_weapon, S_NULL);
  725.         return;
  726.     }
  727.     player->readyweapon = player->pendingweapon;
  728.     P_BringUpWeapon(player);
  729. }
  730.  
  731. //---------------------------------------------------------------------------
  732. //
  733. // PROC A_BeakRaise
  734. //
  735. //---------------------------------------------------------------------------
  736.  
  737. void A_BeakRaise(player_t *player, pspdef_t *psp)
  738. {
  739.     psp->sy = WEAPONTOP;
  740.     P_SetPsprite(player, ps_weapon,
  741.         wpnlev1info[player->readyweapon].readystate);
  742. }
  743.  
  744. //---------------------------------------------------------------------------
  745. //
  746. // PROC A_Raise
  747. //
  748. //---------------------------------------------------------------------------
  749.  
  750. void A_Raise(player_t *player, pspdef_t *psp)
  751. {
  752.     psp->sy -= RAISESPEED;
  753.     if(psp->sy > WEAPONTOP)
  754.     { // Not raised all the way yet
  755.         return;
  756.     }
  757.     psp->sy = WEAPONTOP;
  758.     if(player->powers[pw_weaponlevel2])
  759.     {
  760.         P_SetPsprite(player, ps_weapon,
  761.             wpnlev2info[player->readyweapon].readystate);
  762.     }
  763.     else
  764.     {
  765.         P_SetPsprite(player, ps_weapon,
  766.             wpnlev1info[player->readyweapon].readystate);
  767.     }
  768. }
  769.  
  770. /*
  771. ===============
  772. =
  773. = P_BulletSlope
  774. =
  775. = Sets a slope so a near miss is at aproximately the height of the
  776. = intended target
  777. =
  778. ===============
  779. */
  780.  
  781. void P_BulletSlope (mobj_t *mo)
  782. {
  783.     angle_t        an;
  784.  
  785. //
  786. // see which target is to be aimed at
  787. //
  788.     an = mo->angle;
  789.     bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
  790.     if (!linetarget)
  791.     {
  792.         an += 1<<26;
  793.         bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
  794.         if (!linetarget)
  795.         {
  796.             an -= 2<<26;
  797.             bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
  798.         }
  799.         if (!linetarget)
  800.         {
  801.             an += 2<<26;
  802.             bulletslope = (mo->player->lookdir<<FRACBITS)/173;
  803.         }
  804.     }
  805. }
  806.  
  807. //****************************************************************************
  808. //
  809. // WEAPON ATTACKS
  810. //
  811. //****************************************************************************
  812.  
  813. //----------------------------------------------------------------------------
  814. //
  815. // PROC A_BeakAttackPL1
  816. //
  817. //----------------------------------------------------------------------------
  818.  
  819. void A_BeakAttackPL1(player_t *player, pspdef_t *psp)
  820. {
  821.     angle_t angle;
  822.     int damage;
  823.     int slope;
  824.  
  825.     damage = 1+(P_Random()&3);
  826.     angle = player->mo->angle;
  827.     slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
  828.     PuffType = MT_BEAKPUFF;
  829.     P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
  830.     if(linetarget)
  831.     {
  832.         player->mo->angle = R_PointToAngle2(player->mo->x,
  833.             player->mo->y, linetarget->x, linetarget->y);
  834.     }
  835.     S_StartSound(player->mo, sfx_chicpk1+(P_Random()%3));
  836.     player->chickenPeck = 12;
  837.     psp->tics -= P_Random()&7;
  838. }
  839.  
  840. //----------------------------------------------------------------------------
  841. //
  842. // PROC A_BeakAttackPL2
  843. //
  844. //----------------------------------------------------------------------------
  845.  
  846. void A_BeakAttackPL2(player_t *player, pspdef_t *psp)
  847. {
  848.     angle_t angle;
  849.     int damage;
  850.     int slope;
  851.  
  852.     damage = HITDICE(4);
  853.     angle = player->mo->angle;
  854.     slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
  855.     PuffType = MT_BEAKPUFF;
  856.     P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
  857.     if(linetarget)
  858.     {
  859.         player->mo->angle = R_PointToAngle2(player->mo->x,
  860.             player->mo->y, linetarget->x, linetarget->y);
  861.     }
  862.     S_StartSound(player->mo, sfx_chicpk1+(P_Random()%3));
  863.     player->chickenPeck = 12;
  864.     psp->tics -= P_Random()&3;
  865. }
  866.  
  867. //----------------------------------------------------------------------------
  868. //
  869. // PROC A_StaffAttackPL1
  870. //
  871. //----------------------------------------------------------------------------
  872.  
  873. void A_StaffAttackPL1(player_t *player, pspdef_t *psp)
  874. {
  875.     angle_t angle;
  876.     int damage;
  877.     int slope;
  878.  
  879.     damage = 5+(P_Random()&15);
  880.     angle = player->mo->angle;
  881.     angle += (P_Random()-P_Random())<<18;
  882.     slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
  883.     PuffType = MT_STAFFPUFF;
  884.     P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
  885.     if(linetarget)
  886.     {
  887.         //S_StartSound(player->mo, sfx_stfhit);
  888.         // turn to face target
  889.         player->mo->angle = R_PointToAngle2(player->mo->x,
  890.             player->mo->y, linetarget->x, linetarget->y);
  891.     }
  892. }
  893.  
  894. //----------------------------------------------------------------------------
  895. //
  896. // PROC A_StaffAttackPL2
  897. //
  898. //----------------------------------------------------------------------------
  899.  
  900. void A_StaffAttackPL2(player_t *player, pspdef_t *psp)
  901. {
  902.     angle_t angle;
  903.     int damage;
  904.     int slope;
  905.  
  906.     // P_inter.c:P_DamageMobj() handles target momentums
  907.     damage = 18+(P_Random()&63);
  908.     angle = player->mo->angle;
  909.     angle += (P_Random()-P_Random())<<18;
  910.     slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
  911.     PuffType = MT_STAFFPUFF2;
  912.     P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
  913.     if(linetarget)
  914.     {
  915.         //S_StartSound(player->mo, sfx_stfpow);
  916.         // turn to face target
  917.         player->mo->angle = R_PointToAngle2(player->mo->x,
  918.             player->mo->y, linetarget->x, linetarget->y);
  919.     }
  920. }
  921.  
  922. //----------------------------------------------------------------------------
  923. //
  924. // PROC A_FireBlasterPL1
  925. //
  926. //----------------------------------------------------------------------------
  927.  
  928. void A_FireBlasterPL1(player_t *player, pspdef_t *psp)
  929. {
  930.     mobj_t *mo;
  931.     angle_t angle;
  932.     int damage;
  933.  
  934.     mo = player->mo;
  935.     S_StartSound(mo, sfx_gldhit);
  936.     player->ammo[am_blaster] -= USE_BLSR_AMMO_1;
  937.     P_BulletSlope(mo);
  938.     damage = HITDICE(4);
  939.     angle = mo->angle;
  940.     if(player->refire)
  941.     {
  942.         angle += (P_Random()-P_Random())<<18;
  943.     }
  944.     PuffType = MT_BLASTERPUFF1;
  945.     P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
  946.     S_StartSound(player->mo, sfx_blssht);
  947. }
  948.  
  949. //----------------------------------------------------------------------------
  950. //
  951. // PROC A_FireBlasterPL2
  952. //
  953. //----------------------------------------------------------------------------
  954.  
  955. void A_FireBlasterPL2(player_t *player, pspdef_t *psp)
  956. {
  957.     mobj_t *mo;
  958.  
  959.     player->ammo[am_blaster] -=
  960.         deathmatch ? USE_BLSR_AMMO_1 : USE_BLSR_AMMO_2;
  961.     mo = P_SpawnPlayerMissile(player->mo, MT_BLASTERFX1);
  962.     if(mo)
  963.     {
  964.         mo->thinker.function = P_BlasterMobjThinker;
  965.     }
  966.     S_StartSound(player->mo, sfx_blssht);
  967. }
  968.  
  969. //----------------------------------------------------------------------------
  970. //
  971. // PROC A_FireGoldWandPL1
  972. //
  973. //----------------------------------------------------------------------------
  974.  
  975. void A_FireGoldWandPL1(player_t *player, pspdef_t *psp)
  976. {
  977.     mobj_t *mo;
  978.     angle_t angle;
  979.     int damage;
  980.  
  981.     mo = player->mo;
  982.     player->ammo[am_goldwand] -= USE_GWND_AMMO_1;
  983.     P_BulletSlope(mo);
  984.     damage = 7+(P_Random()&7);
  985.     angle = mo->angle;
  986.     if(player->refire)
  987.     {
  988.         angle += (P_Random()-P_Random())<<18;
  989.     }
  990.     PuffType = MT_GOLDWANDPUFF1;
  991.     P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
  992.     S_StartSound(player->mo, sfx_gldhit);
  993. }
  994.  
  995. //----------------------------------------------------------------------------
  996. //
  997. // PROC A_FireGoldWandPL2
  998. //
  999. //----------------------------------------------------------------------------
  1000.  
  1001. void A_FireGoldWandPL2(player_t *player, pspdef_t *psp)
  1002. {
  1003.     int i;
  1004.     mobj_t *mo;
  1005.     angle_t angle;
  1006.     int damage;
  1007.     fixed_t momz;
  1008.  
  1009.     mo = player->mo;
  1010.     player->ammo[am_goldwand] -=
  1011.         deathmatch ? USE_GWND_AMMO_1 : USE_GWND_AMMO_2;
  1012.     PuffType = MT_GOLDWANDPUFF2;
  1013.     P_BulletSlope(mo);
  1014.     momz = FixedMul(mobjinfo[MT_GOLDWANDFX2].speed, bulletslope);
  1015.     P_SpawnMissileAngle(mo, MT_GOLDWANDFX2, mo->angle-(ANG45/8), momz);
  1016.     P_SpawnMissileAngle(mo, MT_GOLDWANDFX2, mo->angle+(ANG45/8), momz);
  1017.     angle = mo->angle-(ANG45/8);
  1018.     for(i = 0; i < 5; i++)
  1019.     {
  1020.         damage = 1+(P_Random()&7);
  1021.         P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
  1022.         angle += ((ANG45/8)*2)/4;
  1023.     }
  1024.     S_StartSound(player->mo, sfx_gldhit);
  1025. }
  1026.  
  1027. //----------------------------------------------------------------------------
  1028. //
  1029. // PROC A_FireMacePL1B
  1030. //
  1031. //----------------------------------------------------------------------------
  1032.  
  1033. void A_FireMacePL1B(player_t *player, pspdef_t *psp)
  1034. {
  1035.     mobj_t *pmo;
  1036.     mobj_t *ball;
  1037.     angle_t angle;
  1038.  
  1039.     if(player->ammo[am_mace] < USE_MACE_AMMO_1)
  1040.     {
  1041.         return;
  1042.     }
  1043.     player->ammo[am_mace] -= USE_MACE_AMMO_1;
  1044.     pmo = player->mo;
  1045.     ball = P_SpawnMobj(pmo->x, pmo->y, pmo->z+28*FRACUNIT 
  1046.         - FOOTCLIPSIZE*(pmo->flags2&MF2_FEETARECLIPPED != 0), MT_MACEFX2);
  1047.     ball->momz = 2*FRACUNIT+((player->lookdir)<<(FRACBITS-5));
  1048.     angle = pmo->angle;
  1049.     ball->target = pmo;
  1050.     ball->angle = angle;
  1051.     ball->z += (player->lookdir)<<(FRACBITS-4);
  1052.     angle >>= ANGLETOFINESHIFT;
  1053.     ball->momx = (pmo->momx>>1)
  1054.         +FixedMul(ball->info->speed, finecosine[angle]);
  1055.     ball->momy = (pmo->momy>>1)
  1056.         +FixedMul(ball->info->speed, finesine[angle]);
  1057.     S_StartSound(ball, sfx_lobsht);
  1058.     P_CheckMissileSpawn(ball);
  1059. }
  1060.  
  1061. //----------------------------------------------------------------------------
  1062. //
  1063. // PROC A_FireMacePL1
  1064. //
  1065. //----------------------------------------------------------------------------
  1066.  
  1067. void A_FireMacePL1(player_t *player, pspdef_t *psp)
  1068. {
  1069.     mobj_t *ball;
  1070.  
  1071.     if(P_Random() < 28)
  1072.     {
  1073.         A_FireMacePL1B(player, psp);
  1074.         return;
  1075.     }
  1076.     if(player->ammo[am_mace] < USE_MACE_AMMO_1)
  1077.     {
  1078.         return;
  1079.     }
  1080.     player->ammo[am_mace] -= USE_MACE_AMMO_1;
  1081.     psp->sx = ((P_Random()&3)-2)*FRACUNIT;
  1082.     psp->sy = WEAPONTOP+(P_Random()&3)*FRACUNIT;
  1083.     ball = P_SPMAngle(player->mo, MT_MACEFX1, player->mo->angle
  1084.         +(((P_Random()&7)-4)<<24));
  1085.     if(ball)
  1086.     {
  1087.         ball->special1 = 16; // tics till dropoff
  1088.     }
  1089. }
  1090.  
  1091. //----------------------------------------------------------------------------
  1092. //
  1093. // PROC A_MacePL1Check
  1094. //
  1095. //----------------------------------------------------------------------------
  1096.  
  1097. void A_MacePL1Check(mobj_t *ball)
  1098. {
  1099.     angle_t angle;
  1100.  
  1101.     if(ball->special1 == 0)
  1102.     {
  1103.         return;
  1104.     }
  1105.     ball->special1 -= 4;
  1106.     if(ball->special1 > 0)
  1107.     {
  1108.         return;
  1109.     }
  1110.     ball->special1 = 0;
  1111.     ball->flags2 |= MF2_LOGRAV;
  1112.     angle = ball->angle>>ANGLETOFINESHIFT;
  1113.     ball->momx = FixedMul(7*FRACUNIT, finecosine[angle]);
  1114.     ball->momy = FixedMul(7*FRACUNIT, finesine[angle]);
  1115.     ball->momz -= ball->momz>>1;
  1116. }
  1117.  
  1118. //----------------------------------------------------------------------------
  1119. //
  1120. // PROC A_MaceBallImpact
  1121. //
  1122. //----------------------------------------------------------------------------
  1123.  
  1124. void A_MaceBallImpact(mobj_t *ball)
  1125. {
  1126.     if((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID))
  1127.     { // Landed in some sort of liquid
  1128.         P_RemoveMobj(ball);
  1129.         return;
  1130.     }
  1131.     if((ball->health != MAGIC_JUNK) && (ball->z <= ball->floorz)
  1132.         && ball->momz)
  1133.     { // Bounce
  1134.         ball->health = MAGIC_JUNK;
  1135.         ball->momz = (ball->momz*192)>>8;
  1136.         ball->flags2 &= ~MF2_FLOORBOUNCE;
  1137.         P_SetMobjState(ball, ball->info->spawnstate);
  1138.         S_StartSound(ball, sfx_bounce);
  1139.     }
  1140.     else
  1141.     { // Explode
  1142.         ball->flags |= MF_NOGRAVITY;
  1143.         ball->flags2 &= ~MF2_LOGRAV;
  1144.         S_StartSound(ball, sfx_lobhit);
  1145.     }
  1146. }
  1147.  
  1148. //----------------------------------------------------------------------------
  1149. //
  1150. // PROC A_MaceBallImpact2
  1151. //
  1152. //----------------------------------------------------------------------------
  1153.  
  1154. void A_MaceBallImpact2(mobj_t *ball)
  1155. {
  1156.     mobj_t *tiny;
  1157.     angle_t angle;
  1158.  
  1159.     if((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID))
  1160.     { // Landed in some sort of liquid
  1161.         P_RemoveMobj(ball);
  1162.         return;
  1163.     }
  1164.     if((ball->z != ball->floorz) || (ball->momz < 2*FRACUNIT))
  1165.     { // Explode
  1166.         ball->momx = ball->momy = ball->momz = 0;
  1167.         ball->flags |= MF_NOGRAVITY;
  1168.         ball->flags2 &= ~(MF2_LOGRAV|MF2_FLOORBOUNCE);
  1169.     }
  1170.     else
  1171.     { // Bounce
  1172.         ball->momz = (ball->momz*192)>>8;
  1173.         P_SetMobjState(ball, ball->info->spawnstate);
  1174.  
  1175.         tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_MACEFX3);
  1176.         angle = ball->angle+ANG90;
  1177.         tiny->target = ball->target;
  1178.         tiny->angle = angle;
  1179.         angle >>= ANGLETOFINESHIFT;
  1180.         tiny->momx = (ball->momx>>1)+FixedMul(ball->momz-FRACUNIT,
  1181.             finecosine[angle]);
  1182.         tiny->momy = (ball->momy>>1)+FixedMul(ball->momz-FRACUNIT,
  1183.             finesine[angle]);
  1184.         tiny->momz = ball->momz;
  1185.         P_CheckMissileSpawn(tiny);
  1186.  
  1187.         tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_MACEFX3);
  1188.         angle = ball->angle-ANG90;
  1189.         tiny->target = ball->target;
  1190.         tiny->angle = angle;
  1191.         angle >>= ANGLETOFINESHIFT;
  1192.         tiny->momx = (ball->momx>>1)+FixedMul(ball->momz-FRACUNIT,
  1193.             finecosine[angle]);
  1194.         tiny->momy = (ball->momy>>1)+FixedMul(ball->momz-FRACUNIT,
  1195.             finesine[angle]);
  1196.         tiny->momz = ball->momz;
  1197.         P_CheckMissileSpawn(tiny);
  1198.     }
  1199. }
  1200.  
  1201. //----------------------------------------------------------------------------
  1202. //
  1203. // PROC A_FireMacePL2
  1204. //
  1205. //----------------------------------------------------------------------------
  1206.  
  1207. void A_FireMacePL2(player_t *player, pspdef_t *psp)
  1208. {
  1209.     mobj_t *mo;
  1210.  
  1211.     player->ammo[am_mace] -=
  1212.         deathmatch ? USE_MACE_AMMO_1 : USE_MACE_AMMO_2;
  1213.     mo = P_SpawnPlayerMissile(player->mo, MT_MACEFX4);
  1214.     if(mo)
  1215.     {
  1216.         mo->momx += player->mo->momx;
  1217.         mo->momy += player->mo->momy;
  1218.         mo->momz = 2*FRACUNIT+((player->lookdir)<<(FRACBITS-5));
  1219.         if(linetarget)
  1220.         {
  1221.             mo->special1 = (int)linetarget;
  1222.         }
  1223.     }
  1224.     S_StartSound(player->mo, sfx_lobsht);
  1225. }
  1226.  
  1227. //----------------------------------------------------------------------------
  1228. //
  1229. // PROC A_DeathBallImpact
  1230. //
  1231. //----------------------------------------------------------------------------
  1232.  
  1233. void A_DeathBallImpact(mobj_t *ball)
  1234. {
  1235.     int i;
  1236.     mobj_t *target;
  1237.     angle_t angle;
  1238.     boolean newAngle;
  1239.  
  1240.     if((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID))
  1241.     { // Landed in some sort of liquid
  1242.         P_RemoveMobj(ball);
  1243.         return;
  1244.     }
  1245.     if((ball->z <= ball->floorz) && ball->momz)
  1246.     { // Bounce
  1247.         newAngle = false;
  1248.         target = (mobj_t *)ball->special1;
  1249.         if(target)
  1250.         {
  1251.             if(!(target->flags&MF_SHOOTABLE))
  1252.             { // Target died
  1253.                 ball->special1 = 0;
  1254.             }
  1255.             else
  1256.             { // Seek
  1257.                 angle = R_PointToAngle2(ball->x, ball->y,
  1258.                     target->x, target->y);
  1259.                 newAngle = true;
  1260.             }
  1261.         }
  1262.         else
  1263.         { // Find new target
  1264.             angle = 0;
  1265.             for(i = 0; i < 16; i++)
  1266.             {
  1267.                 P_AimLineAttack(ball, angle, 10*64*FRACUNIT);
  1268.                 if(linetarget && ball->target != linetarget)
  1269.                 {
  1270.                     ball->special1 = (int)linetarget;
  1271.                     angle = R_PointToAngle2(ball->x, ball->y,
  1272.                         linetarget->x, linetarget->y);
  1273.                     newAngle = true;
  1274.                     break;
  1275.                 }
  1276.                 angle += ANGLE_45/2;
  1277.             }
  1278.         }
  1279.         if(newAngle)
  1280.         {
  1281.             ball->angle = angle;
  1282.             angle >>= ANGLETOFINESHIFT;
  1283.             ball->momx = FixedMul(ball->info->speed, finecosine[angle]);
  1284.             ball->momy = FixedMul(ball->info->speed, finesine[angle]);
  1285.         }
  1286.         P_SetMobjState(ball, ball->info->spawnstate);
  1287.         S_StartSound(ball, sfx_pstop);
  1288.     }
  1289.     else
  1290.     { // Explode
  1291.         ball->flags |= MF_NOGRAVITY;
  1292.         ball->flags2 &= ~MF2_LOGRAV;
  1293.         S_StartSound(ball, sfx_phohit);
  1294.     }
  1295. }
  1296.  
  1297. //----------------------------------------------------------------------------
  1298. //
  1299. // PROC A_SpawnRippers
  1300. //
  1301. //----------------------------------------------------------------------------
  1302.  
  1303. void A_SpawnRippers(mobj_t *actor)
  1304. {
  1305.     int i;
  1306.     angle_t angle;
  1307.     mobj_t *ripper;
  1308.  
  1309.     for(i = 0; i < 8; i++)
  1310.     {
  1311.         ripper = P_SpawnMobj(actor->x, actor->y, actor->z, MT_RIPPER);
  1312.         angle = i*ANG45;
  1313.         ripper->target = actor->target;
  1314.         ripper->angle = angle;
  1315.         angle >>= ANGLETOFINESHIFT;
  1316.         ripper->momx = FixedMul(ripper->info->speed, finecosine[angle]);
  1317.         ripper->momy = FixedMul(ripper->info->speed, finesine[angle]);
  1318.         P_CheckMissileSpawn(ripper);
  1319.     }
  1320. }
  1321.  
  1322. //----------------------------------------------------------------------------
  1323. //
  1324. // PROC A_FireCrossbowPL1
  1325. //
  1326. //----------------------------------------------------------------------------
  1327.  
  1328. void A_FireCrossbowPL1(player_t *player, pspdef_t *psp)
  1329. {
  1330.     mobj_t *pmo;
  1331.  
  1332.     pmo = player->mo;
  1333.     player->ammo[am_crossbow] -= USE_CBOW_AMMO_1;
  1334.     P_SpawnPlayerMissile(pmo, MT_CRBOWFX1);
  1335.     P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle-(ANG45/10));
  1336.     P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle+(ANG45/10));
  1337. }
  1338.  
  1339. //----------------------------------------------------------------------------
  1340. //
  1341. // PROC A_FireCrossbowPL2
  1342. //
  1343. //----------------------------------------------------------------------------
  1344.  
  1345. void A_FireCrossbowPL2(player_t *player, pspdef_t *psp)
  1346. {
  1347.     mobj_t *pmo;
  1348.  
  1349.     pmo = player->mo;
  1350.     player->ammo[am_crossbow] -=
  1351.         deathmatch ? USE_CBOW_AMMO_1 : USE_CBOW_AMMO_2;
  1352.     P_SpawnPlayerMissile(pmo, MT_CRBOWFX2);
  1353.     P_SPMAngle(pmo, MT_CRBOWFX2, pmo->angle-(ANG45/10));
  1354.     P_SPMAngle(pmo, MT_CRBOWFX2, pmo->angle+(ANG45/10));
  1355.     P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle-(ANG45/5));
  1356.     P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle+(ANG45/5));
  1357. }
  1358.  
  1359. //----------------------------------------------------------------------------
  1360. //
  1361. // PROC A_BoltSpark
  1362. //
  1363. //----------------------------------------------------------------------------
  1364.  
  1365. void A_BoltSpark(mobj_t *bolt)
  1366. {
  1367.     mobj_t *spark;
  1368.  
  1369.     if(P_Random() > 50)
  1370.     {
  1371.         spark = P_SpawnMobj(bolt->x, bolt->y, bolt->z, MT_CRBOWFX4);
  1372.         spark->x += (P_Random()-P_Random())<<10;
  1373.         spark->y += (P_Random()-P_Random())<<10;
  1374.     }
  1375. }
  1376.  
  1377. //----------------------------------------------------------------------------
  1378. //
  1379. // PROC A_FireSkullRodPL1
  1380. //
  1381. //----------------------------------------------------------------------------
  1382.  
  1383. void A_FireSkullRodPL1(player_t *player, pspdef_t *psp)
  1384. {
  1385.     mobj_t *mo;
  1386.  
  1387.     if(player->ammo[am_skullrod] < USE_SKRD_AMMO_1)
  1388.     {
  1389.         return;
  1390.     }
  1391.     player->ammo[am_skullrod] -= USE_SKRD_AMMO_1;
  1392.     mo = P_SpawnPlayerMissile(player->mo, MT_HORNRODFX1);
  1393.     // Randomize the first frame
  1394.     if(mo && P_Random() > 128)
  1395.     {
  1396.         P_SetMobjState(mo, S_HRODFX1_2);
  1397.     }
  1398. }
  1399.  
  1400. //----------------------------------------------------------------------------
  1401. //
  1402. // PROC A_FireSkullRodPL2
  1403. //
  1404. // The special2 field holds the player number that shot the rain missile.
  1405. // The special1 field is used for the seeking routines, then as a counter
  1406. // for the sound looping.
  1407. //
  1408. //----------------------------------------------------------------------------
  1409.  
  1410. void A_FireSkullRodPL2(player_t *player, pspdef_t *psp)
  1411. {
  1412.     player->ammo[am_skullrod] -=
  1413.         deathmatch ? USE_SKRD_AMMO_1 : USE_SKRD_AMMO_2;
  1414.     P_SpawnPlayerMissile(player->mo, MT_HORNRODFX2);
  1415.     // Use MissileMobj instead of the return value from
  1416.     // P_SpawnPlayerMissile because we need to give info to the mobj
  1417.     // even if it exploded immediately.
  1418.     if(netgame)
  1419.     { // Multi-player game
  1420.         MissileMobj->special2 = P_GetPlayerNum(player);
  1421.     }
  1422.     else
  1423.     { // Always use red missiles in single player games
  1424.         MissileMobj->special2 = 2;
  1425.     }
  1426.     if(linetarget)
  1427.     {
  1428.         MissileMobj->special1 = (int)linetarget;
  1429.     }
  1430.     S_StartSound(MissileMobj, sfx_hrnpow);
  1431. }
  1432.  
  1433. //----------------------------------------------------------------------------
  1434. //
  1435. // PROC A_SkullRodPL2Seek
  1436. //
  1437. //----------------------------------------------------------------------------
  1438.  
  1439. void A_SkullRodPL2Seek(mobj_t *actor)
  1440. {
  1441.     P_SeekerMissile(actor, ANGLE_1*10, ANGLE_1*30);
  1442. }
  1443.  
  1444. //----------------------------------------------------------------------------
  1445. //
  1446. // PROC A_AddPlayerRain
  1447. //
  1448. //----------------------------------------------------------------------------
  1449.  
  1450. void A_AddPlayerRain(mobj_t *actor)
  1451. {
  1452.     int playerNum;
  1453.     player_t *player;
  1454.  
  1455.     playerNum = netgame ? actor->special2 : 0;
  1456.     if(!playeringame[playerNum])
  1457.     { // Player left the game
  1458.         return;
  1459.     }
  1460.     player = &players[playerNum];
  1461.     if(player->health <= 0)
  1462.     { // Player is dead
  1463.         return;
  1464.     }
  1465.     if(player->rain1 && player->rain2)
  1466.     { // Terminate an active rain
  1467.         if(player->rain1->health < player->rain2->health)
  1468.         {
  1469.             if(player->rain1->health > 16)
  1470.             {
  1471.                 player->rain1->health = 16;
  1472.             }
  1473.             player->rain1 = NULL;
  1474.         }
  1475.         else
  1476.         {
  1477.             if(player->rain2->health > 16)
  1478.             {
  1479.                 player->rain2->health = 16;
  1480.             }
  1481.             player->rain2 = NULL;
  1482.         }
  1483.     }
  1484.     // Add rain mobj to list
  1485.     if(player->rain1)
  1486.     {
  1487.         player->rain2 = actor;
  1488.     }
  1489.     else
  1490.     {
  1491.         player->rain1 = actor;
  1492.     }
  1493. }
  1494.  
  1495. //----------------------------------------------------------------------------
  1496. //
  1497. // PROC A_SkullRodStorm
  1498. //
  1499. //----------------------------------------------------------------------------
  1500.  
  1501. void A_SkullRodStorm(mobj_t *actor)
  1502. {
  1503.     fixed_t x;
  1504.     fixed_t y;
  1505.     mobj_t *mo;
  1506.     int playerNum;
  1507.     player_t *player;
  1508.  
  1509.     if(actor->health-- == 0)
  1510.     {
  1511.         P_SetMobjState(actor, S_NULL);
  1512.         playerNum = netgame ? actor->special2 : 0;
  1513.         if(!playeringame[playerNum])
  1514.         { // Player left the game
  1515.             return;
  1516.         }
  1517.         player = &players[playerNum];
  1518.         if(player->health <= 0)
  1519.         { // Player is dead
  1520.             return;
  1521.         }
  1522.         if(player->rain1 == actor)
  1523.         {
  1524.             player->rain1 = NULL;
  1525.         }
  1526.         else if(player->rain2 == actor)
  1527.         {
  1528.             player->rain2 = NULL;
  1529.         }
  1530.         return;
  1531.     }
  1532.     if(P_Random() < 25)
  1533.     { // Fudge rain frequency
  1534.         return;
  1535.     }
  1536.     x = actor->x+((P_Random()&127)-64)*FRACUNIT;
  1537.     y = actor->y+((P_Random()&127)-64)*FRACUNIT;
  1538.     mo = P_SpawnMobj(x, y, ONCEILINGZ, MT_RAINPLR1+actor->special2);
  1539.     mo->target = actor->target;
  1540.     mo->momx = 1; // Force collision detection
  1541.     mo->momz = -mo->info->speed;
  1542.     mo->special2 = actor->special2; // Transfer player number
  1543.     P_CheckMissileSpawn(mo);
  1544.     if(!(actor->special1&31))
  1545.     {
  1546.         S_StartSound(actor, sfx_ramrain);
  1547.     }
  1548.     actor->special1++;
  1549. }
  1550.  
  1551. //----------------------------------------------------------------------------
  1552. //
  1553. // PROC A_RainImpact
  1554. //
  1555. //----------------------------------------------------------------------------
  1556.  
  1557. void A_RainImpact(mobj_t *actor)
  1558. {
  1559.     if(actor->z > actor->floorz)
  1560.     {
  1561.         P_SetMobjState(actor, S_RAINAIRXPLR1_1+actor->special2);
  1562.     }
  1563.     else if(P_Random() < 40)
  1564.     {
  1565.         P_HitFloor(actor);
  1566.     }
  1567. }
  1568.  
  1569. //----------------------------------------------------------------------------
  1570. //
  1571. // PROC A_HideInCeiling
  1572. //
  1573. //----------------------------------------------------------------------------
  1574.  
  1575. void A_HideInCeiling(mobj_t *actor)
  1576. {
  1577.     actor->z = actor->ceilingz+4*FRACUNIT;
  1578. }
  1579.  
  1580. //----------------------------------------------------------------------------
  1581. //
  1582. // PROC A_FirePhoenixPL1
  1583. //
  1584. //----------------------------------------------------------------------------
  1585.  
  1586. void A_FirePhoenixPL1(player_t *player, pspdef_t *psp)
  1587. {
  1588.     angle_t angle;
  1589.  
  1590.     player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_1;
  1591.     P_SpawnPlayerMissile(player->mo, MT_PHOENIXFX1);
  1592.     //P_SpawnPlayerMissile(player->mo, MT_MNTRFX2);
  1593.     angle = player->mo->angle+ANG180;
  1594.     angle >>= ANGLETOFINESHIFT;
  1595.     player->mo->momx += FixedMul(4*FRACUNIT, finecosine[angle]);
  1596.     player->mo->momy += FixedMul(4*FRACUNIT, finesine[angle]);
  1597. }
  1598.  
  1599. //----------------------------------------------------------------------------
  1600. //
  1601. // PROC A_PhoenixPuff
  1602. //
  1603. //----------------------------------------------------------------------------
  1604.  
  1605. void A_PhoenixPuff(mobj_t *actor)
  1606. {
  1607.     mobj_t *puff;
  1608.     angle_t angle;
  1609.  
  1610.     P_SeekerMissile(actor, ANGLE_1*5, ANGLE_1*10);
  1611.     puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF);
  1612.     angle = actor->angle+ANG90;
  1613.     angle >>= ANGLETOFINESHIFT;
  1614.     puff->momx = FixedMul(FRACUNIT*1.3, finecosine[angle]);
  1615.     puff->momy = FixedMul(FRACUNIT*1.3, finesine[angle]);
  1616.     puff->momz = 0;
  1617.     puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF);
  1618.     angle = actor->angle-ANG90;
  1619.     angle >>= ANGLETOFINESHIFT;
  1620.     puff->momx = FixedMul(FRACUNIT*1.3, finecosine[angle]);
  1621.     puff->momy = FixedMul(FRACUNIT*1.3, finesine[angle]);
  1622.     puff->momz = 0;
  1623. }
  1624.  
  1625. //----------------------------------------------------------------------------
  1626. //
  1627. // PROC A_InitPhoenixPL2
  1628. //
  1629. //----------------------------------------------------------------------------
  1630.  
  1631. void A_InitPhoenixPL2(player_t *player, pspdef_t *psp)
  1632. {
  1633.     player->flamecount = FLAME_THROWER_TICS;
  1634. }
  1635.  
  1636. //----------------------------------------------------------------------------
  1637. //
  1638. // PROC A_FirePhoenixPL2
  1639. //
  1640. // Flame thrower effect.
  1641. //
  1642. //----------------------------------------------------------------------------
  1643.  
  1644. void A_FirePhoenixPL2(player_t *player, pspdef_t *psp)
  1645. {
  1646.     mobj_t *mo;
  1647.     mobj_t *pmo;
  1648.     angle_t angle;
  1649.     fixed_t x, y, z;
  1650.     fixed_t slope;
  1651.  
  1652.     if(--player->flamecount == 0)
  1653.     { // Out of flame
  1654.         P_SetPsprite(player, ps_weapon, S_PHOENIXATK2_4);
  1655.         player->refire = 0;
  1656.         return;
  1657.     }
  1658.     pmo = player->mo;
  1659.     angle = pmo->angle;
  1660.     x = pmo->x+((P_Random()-P_Random())<<9);
  1661.     y = pmo->y+((P_Random()-P_Random())<<9);
  1662.     z = pmo->z+26*FRACUNIT+((player->lookdir)<<FRACBITS)/173;
  1663.     if(pmo->flags2&MF2_FEETARECLIPPED)
  1664.     {
  1665.         z -= FOOTCLIPSIZE;
  1666.     }
  1667.     slope = ((player->lookdir)<<FRACBITS)/173+(FRACUNIT/10);
  1668.     mo = P_SpawnMobj(x, y, z, MT_PHOENIXFX2);
  1669.     mo->target = pmo;
  1670.     mo->angle = angle;
  1671.     mo->momx = pmo->momx+FixedMul(mo->info->speed,
  1672.         finecosine[angle>>ANGLETOFINESHIFT]);
  1673.     mo->momy = pmo->momy+FixedMul(mo->info->speed,
  1674.         finesine[angle>>ANGLETOFINESHIFT]);
  1675.     mo->momz = FixedMul(mo->info->speed, slope);
  1676.     if(!player->refire || !(leveltime%38))
  1677.     {
  1678.         S_StartSound(player->mo, sfx_phopow);
  1679.     }    
  1680.     P_CheckMissileSpawn(mo);
  1681. }
  1682.  
  1683. //----------------------------------------------------------------------------
  1684. //
  1685. // PROC A_ShutdownPhoenixPL2
  1686. //
  1687. //----------------------------------------------------------------------------
  1688.  
  1689. void A_ShutdownPhoenixPL2(player_t *player, pspdef_t *psp)
  1690. {
  1691.     player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_2;
  1692. }
  1693.  
  1694. //----------------------------------------------------------------------------
  1695. //
  1696. // PROC A_FlameEnd
  1697. //
  1698. //----------------------------------------------------------------------------
  1699.  
  1700. void A_FlameEnd(mobj_t *actor)
  1701. {
  1702.     actor->momz += 1.5*FRACUNIT;
  1703. }
  1704.  
  1705. //----------------------------------------------------------------------------
  1706. //
  1707. // PROC A_FloatPuff
  1708. //
  1709. //----------------------------------------------------------------------------
  1710.  
  1711. void A_FloatPuff(mobj_t *puff)
  1712. {
  1713.     puff->momz += 1.8*FRACUNIT;
  1714. }
  1715.  
  1716. //---------------------------------------------------------------------------
  1717. //
  1718. // PROC A_GauntletAttack
  1719. //
  1720. //---------------------------------------------------------------------------
  1721.  
  1722. void A_GauntletAttack(player_t *player, pspdef_t *psp)
  1723. {
  1724.     angle_t angle;
  1725.     int damage;
  1726.     int slope;
  1727.     int randVal;
  1728.     fixed_t dist;
  1729.  
  1730.     psp->sx = ((P_Random()&3)-2)*FRACUNIT;
  1731.     psp->sy = WEAPONTOP+(P_Random()&3)*FRACUNIT;
  1732.     angle = player->mo->angle;
  1733.     if(player->powers[pw_weaponlevel2])
  1734.     {
  1735.         damage = HITDICE(2);
  1736.         dist = 4*MELEERANGE;
  1737.         angle += (P_Random()-P_Random())<<17;
  1738.         PuffType = MT_GAUNTLETPUFF2;
  1739.     }
  1740.     else
  1741.     {
  1742.         damage = HITDICE(2);
  1743.         dist = MELEERANGE+1;
  1744.         angle += (P_Random()-P_Random())<<18;
  1745.         PuffType = MT_GAUNTLETPUFF1;
  1746.     }
  1747.     slope = P_AimLineAttack(player->mo, angle, dist);
  1748.     P_LineAttack(player->mo, angle, dist, slope, damage);
  1749.     if(!linetarget)
  1750.     {
  1751.         if(P_Random() > 64)
  1752.         {
  1753.             player->extralight = !player->extralight;
  1754.         }
  1755.         S_StartSound(player->mo, sfx_gntful);
  1756.         return;
  1757.     }
  1758.     randVal = P_Random();
  1759.     if(randVal < 64)
  1760.     {
  1761.         player->extralight = 0;
  1762.     }
  1763.     else if(randVal < 160)
  1764.     {
  1765.         player->extralight = 1;
  1766.     }
  1767.     else
  1768.     {
  1769.         player->extralight = 2;
  1770.     }
  1771.     if(player->powers[pw_weaponlevel2])
  1772.     {
  1773.         P_GiveBody(player, damage>>1);
  1774.         S_StartSound(player->mo, sfx_gntpow);
  1775.     }
  1776.     else
  1777.     {
  1778.         S_StartSound(player->mo, sfx_gnthit);
  1779.     }
  1780.     // turn to face target
  1781.     angle = R_PointToAngle2(player->mo->x, player->mo->y,
  1782.         linetarget->x, linetarget->y);
  1783.     if(angle-player->mo->angle > ANG180)
  1784.     {
  1785.         if(angle-player->mo->angle < -ANG90/20)
  1786.             player->mo->angle = angle+ANG90/21;
  1787.         else
  1788.             player->mo->angle -= ANG90/20;
  1789.     }
  1790.     else
  1791.     {
  1792.         if(angle-player->mo->angle > ANG90/20)
  1793.             player->mo->angle = angle-ANG90/21;
  1794.         else
  1795.             player->mo->angle += ANG90/20;
  1796.     }
  1797.     player->mo->flags |= MF_JUSTATTACKED;
  1798. }
  1799.  
  1800. void A_Light0(player_t *player, pspdef_t *psp)
  1801. {
  1802.     player->extralight = 0;
  1803. }
  1804.  
  1805. void A_Light1(player_t *player, pspdef_t *psp)
  1806. {
  1807.     player->extralight = 1;
  1808. }
  1809.  
  1810. void A_Light2(player_t *player, pspdef_t *psp)
  1811. {
  1812.     player->extralight = 2;
  1813. }
  1814.  
  1815. //------------------------------------------------------------------------
  1816. //
  1817. // PROC P_SetupPsprites
  1818. //
  1819. // Called at start of level for each player
  1820. //
  1821. //------------------------------------------------------------------------
  1822.  
  1823. void P_SetupPsprites(player_t *player)
  1824. {
  1825.     int i;
  1826.  
  1827.     // Remove all psprites
  1828.     for(i = 0; i < NUMPSPRITES; i++)
  1829.     {
  1830.         player->psprites[i].state = NULL;
  1831.     }
  1832.     // Spawn the ready weapon
  1833.     player->pendingweapon = player->readyweapon;
  1834.     P_BringUpWeapon(player);
  1835. }
  1836.  
  1837. //------------------------------------------------------------------------
  1838. //
  1839. // PROC P_MovePsprites
  1840. //
  1841. // Called every tic by player thinking routine
  1842. //
  1843. //------------------------------------------------------------------------
  1844.  
  1845. void P_MovePsprites(player_t *player)
  1846. {
  1847.     int i;
  1848.     pspdef_t *psp;
  1849.     state_t *state;
  1850.  
  1851.     psp = &player->psprites[0];
  1852.     for(i = 0; i < NUMPSPRITES; i++, psp++)
  1853.     {
  1854.         if((state = psp->state) != 0) // a null state means not active
  1855.         {
  1856.             // drop tic count and possibly change state
  1857.             if(psp->tics != -1)    // a -1 tic count never changes
  1858.             {
  1859.                 psp->tics--;
  1860.                 if(!psp->tics)
  1861.                 {
  1862.                     P_SetPsprite(player, i, psp->state->nextstate);
  1863.                 }
  1864.             }
  1865.         }
  1866.     }
  1867.     player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx;
  1868.     player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy;
  1869. }
  1870.